package app

import (
	"context"
	"errors"
	"fmt"
	"strings"
	"time"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/app"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/layout"
	"fyne.io/fyne/v2/theme"
	"fyne.io/fyne/v2/widget"
	"go.uber.org/zap"

	"ddl_checker/internal/clipboard"
	"ddl_checker/internal/config"
	"ddl_checker/internal/database"
	guiwidgets "ddl_checker/internal/gui/widgets"
	"ddl_checker/internal/model"
	"ddl_checker/internal/rules"
	"ddl_checker/internal/service"
	"ddl_checker/pkg/logger"
)

// DDLRow 使用model包中的DDLRow定义
type DDLRow = model.DDLRow

// DDLCheckerApp 单行DDL检查应用
type DDLCheckerApp struct {
	MyApp             fyne.App
	Window            fyne.Window
	StatusLabel       *widget.Label
	ResultBox         *guiwidgets.SimpleTextBox
	DBManager         *database.Manager
	ValidationService *service.ValidationService
	ClipboardManager  *clipboard.ClipboardManager

	// 输入字段
	SchemaEntry  *guiwidgets.LinedEntry
	TableEntry   *guiwidgets.LinedEntry
	ScriptInputs map[string]*guiwidgets.ScriptInputField
}

// NewDDLCheckerApp 创建新的DDL检查应用
func NewDDLCheckerApp() *DDLCheckerApp {
	myApp := app.NewWithID("ddl-checker-excel")
	myApp.SetIcon(theme.DocumentIcon())

	window := myApp.NewWindow("DDL Checker") // 简化窗口标题
	window.Resize(fyne.NewSize(900, 800))
	window.SetMaster()

	return &DDLCheckerApp{
		MyApp:             myApp,
		Window:            window,
		ValidationService: service.NewValidationService(nil),
		ScriptInputs:      make(map[string]*guiwidgets.ScriptInputField),
	}
}

// SetClipboardManager 设置剪贴板管理器
func (app *DDLCheckerApp) SetClipboardManager(manager *clipboard.ClipboardManager) {
	app.ClipboardManager = manager
}

// InitializeDatabase 初始化数据库连接
func (app *DDLCheckerApp) InitializeDatabase() error {
	cfg := config.Load()

	logger.Infof("数据库配置: %s@%s:%d/%s",
		cfg.Database.User, cfg.Database.Host, cfg.Database.Port, cfg.Database.Database)

	app.DBManager = database.GetInstance()
	if err := app.DBManager.Initialize(&cfg.Database); err != nil {
		logger.Error("数据库初始化失败", zap.Error(err))
		return errors.New("数据库初始化失败")
	}

	// 更新验证服务的数据库连接
	app.ValidationService = service.NewValidationService(app.DBManager.GetDB())

	// 健康检查
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	if err := app.DBManager.HealthCheck(ctx); err != nil {
		logger.Error("数据库健康检查失败", zap.Error(err))
		return errors.New("数据库健康检查失败")
	}

	logger.Info("数据库连接初始化成功")
	return nil
}

// GetScriptText 获取脚本文本
func (app *DDLCheckerApp) GetScriptText(key string) string {
	if field, exists := app.ScriptInputs[key]; exists {
		return field.Entry.Text()
	}
	return ""
}

// SetScriptText 设置脚本文本
func (app *DDLCheckerApp) SetScriptText(key, text string) {
	if field, exists := app.ScriptInputs[key]; exists {
		field.Entry.SetText(text)
	}
}

// GetCurrentData 获取当前输入数据
func (app *DDLCheckerApp) GetCurrentData() DDLRow {
	return DDLRow{
		Schema:         app.SchemaEntry.Text(),
		Table:          app.TableEntry.Text(),
		Script:         app.GetScriptText("ddl"),
		RollbackScript: app.GetScriptText("rollback"),
	}
}

// SetCurrentData 设置当前输入数据
func (app *DDLCheckerApp) SetCurrentData(data DDLRow) {
	app.SchemaEntry.SetText(data.Schema)
	app.TableEntry.SetText(data.Table)
	app.SetScriptText("ddl", data.Script)
	app.SetScriptText("rollback", data.RollbackScript)
}

// ClearInputFields 清空输入字段
func (app *DDLCheckerApp) ClearInputFields() {
	app.SchemaEntry.SetText("")
	app.TableEntry.SetText("")
	for key := range app.ScriptInputs {
		app.SetScriptText(key, "")
	}
}

// PasteFromClipboard 从剪贴板粘贴Excel数据
func (app *DDLCheckerApp) PasteFromClipboard() {
	// 首先尝试使用Excel剪贴板管理器
	if app.ClipboardManager != nil {
		result, err := app.ClipboardManager.GetExcelData()
		if err == nil && result.Success {
			app.processExcelData(result)
			return
		}
		// Excel解析失败时继续尝试常规方法
	}
	app.StatusLabel.SetText("❌ 剪贴板导入失败")
}

// processExcelData 处理Excel数据
func (app *DDLCheckerApp) processExcelData(result *clipboard.ParseResult) {
	if len(result.Data) == 0 {
		app.StatusLabel.SetText("❌ Excel数据为空")
		return
	}

	// 取第一行数据（如果有标题行，则为第二行）
	dataRow := result.Data[0]
	if len(result.Data) > 1 {
		// 如果有多行，假设第一行是标题，取第二行数据
		dataRow = result.Data[1]
	}

	// 按列位置顺序填充：第1列=Schema, 第2列=Table, 第3列=DDL脚本, 第4列=回滚脚本
	if len(dataRow) >= 1 {
		app.SchemaEntry.SetText(strings.TrimSpace(dataRow[0]))
	}

	if len(dataRow) >= 2 {
		app.TableEntry.SetText(strings.TrimSpace(dataRow[1]))
	}

	if len(dataRow) >= 3 {
		app.SetScriptText("ddl", strings.TrimSpace(dataRow[2]))
	}

	if len(dataRow) >= 4 {
		app.SetScriptText("rollback", strings.TrimSpace(dataRow[3]))
	}

	app.StatusLabel.SetText("✅ 成功从Excel导入数据")
}

// ValidateDDL 验证DDL脚本
func (app *DDLCheckerApp) ValidateDDL() {
	data := app.GetCurrentData()

	// 检查必填字段
	if strings.TrimSpace(data.Schema) == "" {
		app.UpdateResults("❌ **请输入Schema**\n\n")
		return
	}

	if strings.TrimSpace(data.Table) == "" {
		app.UpdateResults("❌ **请输入Table**\n\n")
		return
	}

	if strings.TrimSpace(data.Script) == "" {
		app.UpdateResults("❌ **请输入DDL脚本进行验证**\n\n")
		return
	}

	// 使用新的规则引擎进行验证
	engine := rules.NewRuleEngine()
	checkData := rules.DDLCheckData{
		Schema:         data.Schema,
		Table:          data.Table,
		Script:         data.Script,
		RollbackScript: data.RollbackScript,
	}

	results := engine.Execute(checkData)
	formattedResults := rules.FormatCheckResult(results)

	// 添加验证对象信息
	var builder strings.Builder
	builder.WriteString(fmt.Sprintf("**验证对象: %s.%s**\n\n", data.Schema, data.Table))
	builder.WriteString(formattedResults)

	app.UpdateResults(builder.String())
}

// UpdateResults 更新验证结果（异步）
func (app *DDLCheckerApp) UpdateResults(content string) {
	// 使用goroutine异步更新，避免阻塞主线程
	go func() {
		app.ResultBox.SetText(content)
	}()
}

// CopyResults 复制结果到剪贴板
func (app *DDLCheckerApp) CopyResults() {
	content := app.ResultBox.Text()
	if content == "" {
		app.StatusLabel.SetText("没有可复制的内容")
		return
	}

	clipboardObj := app.MyApp.Driver().AllWindows()[0].Clipboard()
	clipboardObj.SetContent(content)
	app.StatusLabel.SetText("✅ 结果已复制到剪贴板")
}

// BuildUI 构建用户界面
func (app *DDLCheckerApp) BuildUI() {
	// 状态标签
	app.StatusLabel = widget.NewLabel("就绪")
	app.StatusLabel.Alignment = fyne.TextAlignLeading

	// 创建输入和结果区域（内部已包含滚动条）
	inputSection := app.buildInputSection()
	resultSection := app.buildResultSection()

	// 创建垂直分割容器，设置0.65:0.35比例
	vsplit := container.NewVSplit(
		inputSection,  // 输入区域（内部已处理滚动）
		resultSection, // 结果区域（内部已处理滚动）
	)
	vsplit.SetOffset(0.65) // 输入区域占65%，结果区域占35%

	// 创建主容器 - 使用Border布局，状态标签固定在底部
	mainContainer := container.NewBorder(
		nil,             // 顶部
		app.StatusLabel, // 底部（固定状态标签）
		nil,             // 左侧
		nil,             // 右侧
		vsplit,          // 中间内容（可调整分割）
	)

	app.Window.SetContent(mainContainer)

	// 设置快捷键和关闭处理
	app.Window.SetOnClosed(func() {
		if app.DBManager != nil {
			app.DBManager.Close()
		}
	})
}

// buildInputSection 构建输入区域部分
func (app *DDLCheckerApp) buildInputSection() fyne.CanvasObject {
	// 输入标题和按钮容器 - 固定在顶部，不滚动
	titleContainer := container.NewBorder(
		nil,                           // 顶部
		nil,                           // 底部
		nil,                           // 左侧
		app.buildInputButtons(),       // 右侧按钮
		widget.NewLabel("→ DDL 输入区域"), // 标题
	)

	// 输入内容容器 - 可滚动
	scrollableContent := container.NewScroll(app.buildInputForm())

	// 整个输入区域容器 - title固定，内容可滚动
	return container.NewBorder(
		titleContainer,    // 顶部标题和按钮（固定，不滚动）
		nil,               // 底部
		nil,               // 左侧
		nil,               // 右侧
		scrollableContent, // 中间内容（可滚动）
	)
}

// buildInputButtons 构建输入区域按钮
func (app *DDLCheckerApp) buildInputButtons() fyne.CanvasObject {
	// 使用HBox添加spacer推动按钮到右侧，实现右对齐
	buttonContainer := container.NewHBox()
	buttonContainer.Add(layout.NewSpacer()) // 推动按钮到右侧
	buttonContainer.Add(widget.NewButton("从剪贴板导入", app.PasteFromClipboard))
	buttonContainer.Add(widget.NewButton("清空", app.ClearInputFields))
	buttonContainer.Add(widget.NewButton("连接数据库", func() {
		if err := app.InitializeDatabase(); err != nil {
			app.StatusLabel.SetText(fmt.Sprintf("❌ %s", err.Error()))
		} else {
			app.StatusLabel.SetText("✅ 数据库连接成功")
		}
	}))
	buttonContainer.Add(widget.NewButton("验证 DDL", app.ValidateDDL))
	return buttonContainer
}

// buildInputForm 构建输入表单
func (app *DDLCheckerApp) buildInputForm() fyne.CanvasObject {
	// Schema输入 - 使用ScriptInputField，高度为1行
	schemaConfig := guiwidgets.ScriptInputConfig{
		Label:       "Schema",
		PlaceHolder: "例如: ec, fc, hr",
		MinRows:     1, // 1行高度
	}
	schemaInput := guiwidgets.NewScriptInputField(schemaConfig)
	app.SchemaEntry = schemaInput.Entry
	app.ScriptInputs["schema"] = schemaInput

	// Table输入 - 使用ScriptInputField，高度为1行
	tableConfig := guiwidgets.ScriptInputConfig{
		Label:       "Table",
		PlaceHolder: "例如: t_user, t_product",
		MinRows:     1, // 1行高度
	}
	tableInput := guiwidgets.NewScriptInputField(tableConfig)
	app.TableEntry = tableInput.Entry
	app.ScriptInputs["table"] = tableInput

	// DDL脚本输入
	ddlConfig := guiwidgets.ScriptInputConfig{
		Label:       "DDL Script",
		PlaceHolder: "输入 DDL 脚本，例如：\nCREATE TABLE ec.t_user (\n  user_id VARCHAR(64) PRIMARY KEY,\n  user_name VARCHAR(100)\n);",
		MinRows:     7,
	}
	ddlInput := guiwidgets.NewScriptInputField(ddlConfig)
	app.ScriptInputs["ddl"] = ddlInput

	// 回滚脚本输入
	rollbackConfig := guiwidgets.ScriptInputConfig{
		Label:       "Rollback Script",
		PlaceHolder: "输入回滚脚本（可选）",
		MinRows:     3,
	}
	rollbackInput := guiwidgets.NewScriptInputField(rollbackConfig)
	app.ScriptInputs["rollback"] = rollbackInput

	// 创建表单布局 - 使用Form布局确保label固定宽度，输入框填充剩余空间
	form := &widget.Form{
		Items: []*widget.FormItem{
			{
				Text:   "Schema:",
				Widget: schemaInput.Entry,
			},
			{
				Text:   "Table:",
				Widget: tableInput.Entry,
			},
			{
				Text:   "DDL Script:",
				Widget: ddlInput.Entry,
			},
			{
				Text:   "Rollback Script:",
				Widget: rollbackInput.Entry,
			},
		},
	}

	// 设置表单填充可用空间
	return container.NewBorder(nil, nil, nil, nil, form)
}

// buildResultSection 构建结果区域部分
func (app *DDLCheckerApp) buildResultSection() fyne.CanvasObject {
	// 结果标题和按钮容器 - 固定在顶部，不滚动
	titleContainer := container.NewBorder(
		nil,                       // 顶部
		nil,                       // 底部
		nil,                       // 左侧
		app.buildResultButtons(),  // 右侧按钮
		widget.NewLabel("→ 验证结果"), // 标题
	)

	// 结果文本框 - 简单文本显示
	app.ResultBox = guiwidgets.NewSimpleTextBox(8)

	// 整个结果区域容器 - title固定，内容可滚动
	return container.NewBorder(
		titleContainer, // 顶部标题和按钮（固定，不滚动）
		nil,            // 底部
		nil,            // 左侧
		nil,            // 右侧
		app.ResultBox,  // 中间内容（内置滚动）
	)
}

// buildResultButtons 构建结果区域按钮
func (app *DDLCheckerApp) buildResultButtons() fyne.CanvasObject {
	// 使用HBox添加spacer推动按钮到右侧，实现右对齐
	buttonContainer := container.NewHBox()
	buttonContainer.Add(layout.NewSpacer()) // 推动按钮到右侧
	buttonContainer.Add(widget.NewButton("复制结果", app.CopyResults))
	return buttonContainer
}

// Run 运行应用
func (app *DDLCheckerApp) Run() {
	app.BuildUI()
	app.Window.ShowAndRun()
}
